home *** CD-ROM | disk | FTP | other *** search
- _YOUR OWN DISK DUPLICATOR PROGRAM_
- by Al Williams
-
- [LISTING ONE]
-
- /****************************************************************
- * CB386.H - include file for CopyBuilder 386 *
- * See makefile for compile directives -- Al Williams *
- ****************************************************************/
- #define NRTRIES 3 /* number of times to retry disk ops */
-
- /* force codebuilder to not align */
- #pragma align(_bpb=1)
- /* structre of disk BPB */
- extern struct _bpb
- {
- unsigned char jump[3];
- char oemname[8];
- unsigned short bytespersec;
- unsigned char secperclust;
- unsigned short ressectors;
- unsigned char nrfats;
- unsigned short rootsize;
- unsigned short nrsectors;
- char media;
- unsigned short fatsectors;
- unsigned short secpertrack;
- unsigned short nrheads;
- unsigned int hiddensecs;
- unsigned int hugesectors;
- unsigned char physdrive;
- char notused;
- unsigned char signature; /* should be 0x29 */
- unsigned int serno;
- char label[11];
- char type[8];
- char pad[512-60]; /* rest of 512 byte sector */
- } bpb;
- /* various globals */
- extern int driveno;
- extern unsigned disksize;
- extern unsigned sectorct;
- /* disk image buffer */
- extern unsigned char *diskbuf;
- /* DOS buffer used to communicate with BIOS */
- extern char *dosbuf;
- /* set by critical errors */
- extern int critical_err;
- /* information on buffer */
- extern struct _bufinfo
- {
- char title[65];
- unsigned size;
- unsigned short copies;
- char source[13];
- /* checksums (stored and computed) */
- unsigned short csum, ccsum;
- short dirty;
- } bufinfo;
- extern void (*slbreak)(); /* place to hook break handler */
- /* holds disk format command */
- extern char fmtcmd[];
- /* additional break handler */
- extern void (*when_break)();
- /* prototypes for break handlers */
- void load_break();
- void save_break();
- /* general prototypes */
- int sector_read(int head, int track, int sector, int drive,
- unsigned char *buf,unsigned count);
- int sector_write(int head, int track, int sector, int drive,
- unsigned char *buf,unsigned count);
- /* disable reboot */
- void noreboot(void);
- void okreboot(void);
-
-
-
-
- [LISTING TWO]
-
-
- /****************************************************************
- * CB386.C - main file for CopyBuilder 386 *
- * See makefile for compile directives -- Al Williams *
- ****************************************************************/
- #include <stdio.h>
- #include <dos.h>
- #include <ctype.h>
- #include "cb386.h"
- #include "display.h"
-
- /* current drive number */
- int driveno;
- /* current bios parameter block */
- struct _bpb bpb;
- /* size of disk */
- unsigned disksize;
- /* information about buffer */
- struct _bufinfo bufinfo;
- /* number of sectors */
- unsigned sectorct;
- /* storage for disk image */
- unsigned char *diskbuf;
- /* set when a critical error occurs */
- int critical_err;
- /* DOS buffer for disk BIOS reads and writes */
- char *dosbuf;
- /* text of format command */
- char fmtcmd[129];
- /* set when a critical error occurs */
- int critical_err;
- /* critical error messages */
- static char *cmsgs[]=
- {
- "Write protect",
- "Unknown unit",
- "Drive not ready",
- "Unknown command",
- "CRC error",
- "Bad Request",
- "Seek error",
- "Unknown media",
- "Sector not found",
- "Out of paper",
- "Write error",
- "Read error",
- "General failure",
- "Unknown",
- "Unknown",
- "Invalid change"
- };
- /* Critical error handler */
- void cerror(int dev,int code)
- {
- char msg[81];
- int choice;
- critical_err=code&=0xFF;
- sprintf(msg,"Critical error: %s (Retry, Fail, Ignore)", cmsgs[code]);
- choice=prompt(msg,"RIF",ERRCOLOR);
- if (choice==0) choice=_HARDERR_RETRY;
- else if (choice==1) choice=_HARDERR_IGNORE;
- else choice=_HARDERR_FAIL; /* F or ESC */
- _hardresume(choice);
- }
- /* main program */
- main(int argc,char *argv[])
- {
- /* set up critical error handler */
- _harderr(cerror);
- if (argc>2||argv[1][0]=='?'||argv[1][1]=='?')
- error("CopyBuilder 386 by Al Williams\n"
- "A diskette duplication system\n"
- "Usage: CB386 [drive]\n");
- /* save current drive/directory */
- cdsave();
- /* set up video mode and detect monitor type */
- vidmode();
- /* if mono monitor, set up neutral colors */
- if (mono)
- {
- TEXTCOLOR=7;
- SOCOLOR=0x70;
- ERRCOLOR=1;
- HELPCOLOR=7;
- }
- /* reset title, etc. */
- strcpy(bufinfo.title,"<EMPTY>");
- strcpy(bufinfo.source,"N/A");
- strcpy(fmtcmd,"format");
- noreboot();
- /* if user asked for a disk on the command line, read it */
- if (argc==2)
- {
- /* show a display */
- disp();
- /* read the disk */
- read_disk(*argv[1]);
- }
- /* goto main menu */
- menu();
- }
- /* Non-interactive error routine */
- error(char *s)
- {
- printf("\n%s\n",s);
- cdrestore();
- exit(1);
- }
- /* compute checksum
- add sixteen bit words and wrap carry around */
- checksum()
- {
- unsigned char *bufp=diskbuf;
- int i=bufinfo.size;
- unsigned short cksum=0;
- unsigned cksum1;
- while (i--)
- {
- cksum1=cksum;
- cksum1+=*bufp++;
- cksum=cksum1&0xFFFF;
- if (cksum1&0xFFFF0000)
- cksum++;
- }
- bufinfo.ccsum=cksum;
- return cksum;
- }
- /* Format a disk in the indicated drive */
- format(int driveno)
- {
- char fcmd[80];
- int stat;
- /* build command line */
- sprintf(fcmd,"%s %c:",fmtcmd,driveno+'A');
- /* save video */
- vidsave();
- /* execute command */
- stat=system(fcmd);
- vidrestore();
- if (stat==-1) advise("Unable to execute format program");
- }
- /* turn the blinking -wait- on at bottom of screen */
- wait_on()
- {
- int ocolor=color;
- color=SOCOLOR|0x80; /* make it blink */
- goxy(0,24);
- clreol();
- goxy(37,24);
- printfc("-WAIT-");
- curshide();
- color=ocolor;
- }
- /* turn the blinking -wait- off at bottom of screen */
- wait_off()
- {
- goxy(0,24);
- clreol();
- }
-
-
-
- [LISTING THREE]
-
- /****************************************************************
- * FILEIO.C File oriented I/O routines for CB386 *
- * See makefile for compile directives -- Al Williams *
- ****************************************************************/
- #include <stdio.h>
- #include <malloc.h>
- #include <errno.h>
- #include "cb386.h"
- #include "display.h"
-
- void (*slbreak)(); /* place to hook break handler */
-
- /* ^C handler when saving -- used in DISKIO.C too */
- void save_break()
- {
- advise("\aOperation aborted");
- if (slbreak) slbreak();
- when_break=slbreak;
- }
- /* ^C handler when loading -- used in DISKIO.C too */
- void load_break()
- {
- cleanup();
- when_break=slbreak;
- }
- /* Clean up an aborted load */
- cleanup()
- {
- if (diskbuf) free(diskbuf);
- diskbuf=NULL;
- memset(&bufinfo,0,sizeof(bufinfo));
- strcpy(bufinfo.title,"<EMPTY>");
- strcpy(bufinfo.source,"N/A");
- }
- /* save disk image to a file */
- m_save()
- {
- slbreak=when_break;
- when_break=save_break;
- saveit();
- when_break=slbreak;
- slbreak=NULL;
- }
- /* load disk image to a file */
- m_load()
- {
- slbreak=when_break;
- when_break=load_break;
- loadit();
- when_break=slbreak;
- slbreak=NULL;
- }
- /* actual routine to save data */
- saveit()
- {
- char fn[66];
- FILE *f=NULL;
- int cnt1;
- /* if no data to save, forget it */
- if (!diskbuf)
- {
- advise("No disk image in memory");
- return;
- }
- /* get a file name */
- if (!getfilen(fn,65)) return;
- critical_err=0;
- /* check if the file already exists */
- if (!access(fn,0))
- {
- if (prompt("\aFile exists. Overwrite? (Y/N)"
- ,"NY",TEXTCOLOR)<=0)
- return;
- }
- /* if checking for the file caused a critical error,
- don't even try to open the file */
- if (!critical_err) f=fopen(fn,"wb");
-
- /* if the file can't be opened (or wasn't because of
- a critical error, forget it */
- if (!f)
- {
- advise("Can't open file for writing");
- return;
- }
- /* Get a title */
- if (ask("Title: ",NULL,TEXTCOLOR,64,fn,NULL)==-1) return;
- /* only change title if new one was entered */
- if (*fn) strcpy(bufinfo.title,fn);
- /* Turn the wait indicator on */
- wait_on();
- /* set dirty bit in image. copies/source/csum are meaningless */
- bufinfo.dirty=1;
- /* write signature */
- putw('C386',f);
- /* write size of bufinfo */
- putw(sizeof(struct _bufinfo),f);
- /* write bufinfo */
- fwrite(&bufinfo,1,sizeof(struct _bufinfo),f);
- /* write entire buffer in one swoop */
- cnt1=fwrite(diskbuf,1,bufinfo.size,f);
- /* one | is deliberate here -- we always want to fclose */
- if (ferror(f)|fclose(f)|(cnt1!=bufinfo.size))
- advise("\aError writing to file");
- else
- bufinfo.dirty=0;
- wait_off();
- }
- /* routine to actually load file to disk image */
- loadit()
- {
- char fn[66];
- FILE *f;
- int cnt,cnt1;
- /* if buffer is full, confirm */
- if (!dirtyquery()) return;
- /* get file name */
- if (!getfilen(fn,65)) return;
- /* open it */
- f=fopen(fn,"rb");
- /* can't open it, forget it */
- if (!f)
- {
- advise("Can't open file");
- return;
- }
- /* Turn wait indicator on */
- wait_on();
- /* check file type */
- cnt=getw(f);
- if (cnt!='C386')
- {
- advise("Not a C386 image file");
- return;
- }
- /* get size of bufinfo structure */
- cnt=getw(f);
- /* new versions of C386 can't make bufinfo smaller, only larger
- at the end */
- fread(&bufinfo,1,cnt,f);
- /* kill old image */
- if (diskbuf) free(diskbuf);
- /* allocate new image based on size */
- diskbuf=malloc(bufinfo.size);
- if (!diskbuf)
- {
- advise("Insufficient memory");
- cleanup();
- fclose(f);
- return;
- }
- /* read it all in */
- cnt1=fread(diskbuf,1,bufinfo.size,f);
- /* one | is deliberate here also (see saveit(), above) */
- if (ferror(f)|fclose(f)|(cnt1!=bufinfo.size))
- {
- advise("Error reading file");
- cleanup();
- return;
- }
- checksum();
- strcpy(bufinfo.source,fn);
- bufinfo.copies=0;
- wait_off();
- }
-
-
-
-
-
- [LISTING FOUR]
-
- /****************************************************************
- * REBOOT.C - Disable ^ALT-DEL for CodeBuilder programs *
- * Al Williams -- August 1991 *
- ****************************************************************/
- #include <stdio.h>
- #include <i32.h>
- #include <stk.h>
- #include <dos.h>
- #include <conio.h>
-
- /* When running DOS we replace the keyboard interrupt
- (INT 9) */
- /* old INT 9 handler */
- static void (*oldint9)();
- #pragma interrupt(ourint9)
- /* replacement interrupt handler */
- static void ourint9()
- {
- int code,temp;
- /* pointer to CodeBuilder stack frames */
- _XSTACK *frame=_get_stk_frame();
- /* pointer to BIOS shift status byte */
- unsigned char *shift_status=(unsigned char *)0x417;
- /* read keyboard */
- code=inp(0x60);
- /* DEL is scan code 0x53 -- if *shift_status&0xc==0xc then shift
- and Alt are down */
- if (code!=0x53||(*shift_status&0xc)!=0xc) _chain_intr(oldint9);
- /* will not allow ^ALT-DEL */
- /* consume key from keyboard */
- temp=inp(0x61);
- outp(0x61,temp|0x80);
- outp(0x61,temp);
- outp(0x20,0x20);
- /* Tell CodeBuilder not to reissue interrupt */
- frame->opts=_STK_NOINT;
- return;
- }
- /* This function locks the page ourint9 is on so it can't be swapped out.
- 4K is the minimum size, and surely ourint9 isn't that big.... */
- static lockint9(int flag)
- {
- static lock=0;
- if (flag!=lock)
- {
- lock=flag;
- if (flag)
- _dpmi_lockregion(ourint9,4096);
- else
- _dpmi_unlockregion(ourint9,4096);
- }
- }
- /********************** External interfaces ******************/
- /* Disable ^ALT-DEL */
- void noreboot()
- {
- lockint9(1);
- oldint9=_dos_getvect(9);
- _dos_setvect(9,ourint9);
- }
- /* Enable ^ALT-DEL */
- void okreboot()
- {
- lockint9(0);
- _dos_setvect(9,oldint9);
- }
-
-
-
-
- [LISTING FIVE]
-
- /****************************************************************
- * DISPLAY.C general purpose Microsoft C text display library *
- * See also DISPLAY.H DIRPICK.C, and HISTO.C -- Al Williams *
- ****************************************************************/
- #include <stdio.h>
- #include <dos.h>
- #include <string.h>
- #include <stdarg.h>
- #include "display.h"
-
- /* global variable sets color of output */
- int color=7;
- /* primary colors for color monitor (see display.h) */
- int colors[4]={ 0x1e, 0x70, 0x1c, 0x7e };
- /* 1=mono monitor, 0=color, -1=unknown */
- int mono=-1;
- /* set video mode and detect mono monitor
- this should always be called first */
- void vidmode()
- {
- union REGS r;
- if (mono<0)
- {
- r.h.ah=0xf;
- int86(0x10,&r,&r);
- mono=r.h.al==7;
- }
- r.x.ax=mono?7:3;
- int86(0x10,&r,&r);
- r.x.ax=0x500;
- int86(0x10,&r,&r);
- }
- /* goto point x,y (from 0-79 and 0-24) */
- void goxy(int x,int y)
- {
- union REGS r;
- r.h.ah=2;
- r.h.dh=y;
- r.h.dl=x;
- r.h.bh=0;
- int86(0x10,&r,&r);
- }
- /* clear screen region */
- void clears(int x0, int y0,int x1,int y1)
- {
- union REGS r;
- r.x.ax=0x600;
- r.h.bh=color;
- r.h.ch=y0;
- r.h.cl=x0;
- r.h.dh=y1;
- r.h.dl=x1;
- int86(0x10,&r,&r);
- goxy(0,0);
- }
- /* get x,y position */
- void getxy(int *x,int *y)
- {
- union REGS r;
- r.h.ah=3;
- r.h.bh=0;
- int86(0x10,&r,&r);
- *x=r.h.dl;
- *y=r.h.dh;
- }
- /* write count characters
- -- handle \r, \n, backspace, and \a
- updates the cursor if count==1 (w/o line wrap)
- otherwise, the cursor doesn't move */
- void writecc(int c,int count)
- {
- union REGS r;
- /* PS/2 BIOS tries to print 0 characters! */
- if (count<=0) return;
- /* if bell character... */
- if (c=='\a')
- {
- /* use function 0eH to do count bells */
- while (count--)
- {
- r.x.ax=0xe00|'\a';
- r.x.bx=0;
- int86(0x10,&r,&r);
- }
- return;
- }
- /* if regular character (not \n or \r or bs) */
- if (c!='\n'&&c!='\r'&&c!=8)
- {
- /* print regular character */
- r.h.ah=9;
- r.h.al=c;
- r.h.bh=0;
- r.h.bl=color;
- r.x.cx=count;
- int86(0x10,&r,&r);
- /* if count isn't 1 return else do cursor update
- NOTE: \n \r always update cursor */
- if (count!=1) return;
- }
- /* get cursor position */
- r.h.ah=3;
- r.h.bh=0;
- int86(0x10,&r,&r);
- /* if \r, zero x coordinate
- Note that 100 \r's is the same as 1 */
- if (c=='\r')
- r.h.dl=0;
- /* if \n, increment y coordinate by count */
- else if (c=='\n')
- r.h.dh+=count;
- /* if backspace back up by count or to start of line */
- else if (c==8)
- r.h.dl-=r.h.dl>count?count:r.h.dl;
- else
- /* bump x coordinate. Assume it won't wrap over */
- r.h.dl++;
- r.h.ah=2;
- int86(0x10,&r,&r);
- }
- /* write a string using writec, a writecc macro
- (see display.h) */
- void writes(char *s)
- {
- while (*s) writec(*s++);
- }
- /* printf using writecc max length 99 */
- int printfc(char *fmt,...)
- {
- int rc;
- char outbuf[100];
- va_list aptr;
- va_start(aptr,fmt);
- rc=vsprintf(outbuf,fmt,aptr);
- writes(outbuf);
- return rc;
- }
- /* prompt for single key @ coordinates x,y
- use str as prompt, resp is valid keys, pcolor
- is the color to use (0 for same color). Alpha characters
- in resp should be upper case. If resp is "" then all
- characters are valid. If resp is NULL then any alpha
- character is valid.
- returns:
- -1 if ESC pressed
- index of character if resp is valid
- character if resp is NULL or ""
- */
- int prompt_at(int x, int y, char *str,char *resp,int pcolor)
- {
- int ocolor,c;
- char *index;
- goxy(x,y);
- ocolor=color;
- if (pcolor) color=pcolor;
- /* clear to end of line */
- clreol();
- writes(str);
- while (1)
- {
- /* get key */
- c=getch();
- if (!c)
- {
- /* ignore extended keys */
- getch();
- continue;
- }
- /* if esc quit */
- if (c==27) break;
- /* shift upper */
- c=toupper(c);
- /* if resp in not null, check it */
- if (resp&&(index=strchr(resp,c))) break;
- /* if resp is null, check for alpha */
- if (resp==NULL&&isalpha(c)) break;
- /* if resp=="" then anything is OK */
- if (resp&&!*resp) break;
- }
- color=ocolor;
- goxy(x,y);
- clreol();
- curshide();
- return c==27?-1:resp&&*resp?index-resp:c;
- }
- /* prompt for input @x,y. Prompt with promptstr valid is a string of valid
- input characters (if NULL, all characters are OK., clr is the color
- (0 for same), len is the input length, buf is the buffer (should be at
- least len+1 long, and help is an optional help string (use NULL for the
- default help). returns: -1 if ESC # of characters input otherwise
- You can use the backspace key to edit entries */
- int ask_at(int x, int y, char *promptstr,char *valid,
- int clr,int len,char *buf,char *help)
- {
- int count=0,c,ocolor=color;
- char *bp=buf;
- /* clear buffer */
- memset(buf,0,len+1);
- /* set color, goto input line, and clear it */
- if (clr) color=clr;
- goxy(x,y);
- clreol();
- /* write prompt */
- writes(promptstr);
- /* main loop */
- while (1)
- {
- /* get a character. Extended keys are <0 */
- c=getch();
- if (!c) c=-getch();
- /* handle backspace */
- if (c==8)
- {
- if (bp!=buf)
- {
- bp--;
- writec(8);
- writec(' ');
- writec(8);
- *bp='\0';
- count--;
- }
- continue;
- }
- /* Escape or enter ends input */
- if (c=='\r'||c==27)
- {
- /* restore color */
- color=ocolor;
- /* clear line */
- goxy(x,y);
- clreol();
- curshide();
- /* return */
- return c==27?-1:count;
- }
- /* If F1 give help */
- if (c==-59)
- {
- vidsave();
- prompt(help?help:
- " Use <ENTER> to accept, <ESC> to quit, <Backspace>"
- " to correct.","",SOCOLOR);
- vidrestore();
- continue;
- }
- /* ignore other extended keys (c<0) or regular keys if
- at input limit (count==len) */
- if (count==len||c<0) continue;
- /* if not valid character, ignore */
- if (valid&&!strchr(valid,c)) continue;
- /* echo input character */
- writec(c);
- /* store in buffer */
- *bp++=c;
- /* update count */
- count++;
- }
- }
- /* routines to save and restore the video context */
- /* places to save things */
- static char vbuf[4096];
- static int save_xy,save_color;
- /* save video */
- void vidsave()
- {
- union REGS r;
- save_color=color;
- r.h.ah=3;
- r.h.bh=0;
- int86(0x10,&r,&r);
- save_xy=r.x.dx;
- memcpy((void *)vbuf,(void *)(mono?0xb0000:0xb8000),4096);
- }
- /* restore video */
- void vidrestore()
- {
- union REGS r;
- memcpy((void *)(mono?0xb0000:0xb8000),(void *)vbuf,4096);
- color=save_color;
- r.h.ah=2;
- r.h.bh=0;
- r.x.dx=save_xy;
- int86(0x10,&r,&r);
- }
-
-
-
- [LISTING SIX]
-
- /******************************************************************
- * TIMING.C - simple non-rigorous benchmark for Phar Lap's *
- * 286 | DOS Extender & Intel 386 CodeBuilder *
- * Compile with: ICC timing.c graphics.lib (386 protected mode) *
- * OR: *
- * CL -AL -Lp -G2 -Ox timing.c graphp.obj llibpe.lib graphics.lib *
- * (286 protected mode) *
- * OR: *
- * CL -AL -G2 -Ox timing.c graphics.lib *
- * (real mode) *
- ******************************************************************/
- #include <stdio.h>
- #include <graph.h>
- #include <time.h>
-
- #define time_mark time_it(0)
- #define time_done time_it(1)
-
- main()
- {
- printf("Timing graphics operations\n");
- time_mark;
- gtest();
- time_done;
- printf("Timing file operations\n");
- time_mark;
- ftest();
- time_done;
- exit(0);
- }
- /* Function to mark times */
- int time_it(int flag)
- {
- static clock_t sttime;
- unsigned s;
- if (!flag)
- {
- sttime=clock();
- }
- else
- {
- s=(clock()-sttime)/CLK_TCK;
- printf("Elapsed time: %d seconds\n",s);
- }
- return 0;
- }
- /* Graphics test -- must have VGA */
- int gtest()
- {
- int i,x,y;
- _setvideomode(_MRES256COLOR);
- for (i=1;i<11;i++)
- {
- _setcolor(i);
- for (y=0;y<199;y++)
- for (x=0;x<319;x++)
- _setpixel(x,y);
- }
- _setvideomode(_DEFAULTMODE);
- return 0;
- }
- /* File test -- assumes 320K free on current drive */
- char filedata[64000];
- int ftest()
- {
- FILE *tfile;
- int i,j;
- for (j=0;j<10;j++)
- {
- tfile=fopen("~~TIMING.~@~","w");
- if (!tfile)
- {
- perror("TIMING");
- exit(1);
- }
- for (i=0;i<5;i++)
- fwrite(filedata,sizeof(filedata),1,tfile);
- if (fclose(tfile))
- {
- perror("TIMING");
- }
- unlink("~~TIMING.~@~");
- }
- return 0;
- }
-
-
-